/*
 * Copyright (C) 2009, Edmundo Albuquerque de Souza e Silva.
 *
 * This file may be distributed under the terms of the Q Public License
 * as defined by Trolltech AS of Norway and appearing in the file
 * LICENSE.QPL included in the packaging of this file.
 *
 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

package net.sf.fmj.ui.wizards;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import javax.media.Format;
import javax.media.control.TrackControl;
import javax.media.format.AudioFormat;
import javax.media.protocol.ContentDescriptor;

import net.sf.fmj.ui.wizard.WizardPanelDescriptor;
import net.sf.fmj.utility.LoggerSingleton;


/**
 * 
 * 
 *
 */
public class ContentAndTrackFormatPanelDescriptor extends WizardPanelDescriptor
{
    
	private static final Logger logger = LoggerSingleton.logger;

    public static final String IDENTIFIER = ContentAndTrackFormatPanelDescriptor.class.getName();
    
    private final ContentAndTrackFormatPanel panel;
    private final ProcessorWizardConfig config;
    private final ProcessorWizardResult result;
    private final Object nextPanelDescriptor;
    private final ContentDescriptorFilter contentDescriptorFilter;
    public ContentAndTrackFormatPanelDescriptor(Object nextPanelDescriptor, ContentDescriptorFilter contentDescriptorFilter,
    		final ProcessorWizardConfig config, ProcessorWizardResult result) 
    {
        
        panel = new ContentAndTrackFormatPanel();
        
        setPanelDescriptorIdentifier(IDENTIFIER);
        setPanelComponent(panel);
        this.config = config;
        this.result = result;
        this.nextPanelDescriptor = nextPanelDescriptor;
        this.contentDescriptorFilter = contentDescriptorFilter;
        
    }
    
    public Object getNextPanelDescriptor() 
    {
        return nextPanelDescriptor;
    }
    
    public Object getBackPanelDescriptor() 
    {
        return ChooseSourcePanelDescriptor.IDENTIFIER;
    }
    
    public ContentAndTrackFormatPanel getContentAndTrackFormatPanel()
    {	return (ContentAndTrackFormatPanel) getPanelComponent();
    }
    
    private boolean isCompatible(ContentDescriptor d)
    {
    	return contentDescriptorFilter.isCompatible(d);

    	
    }
    
    private ContentDescriptor[] compatible(ContentDescriptor[] contentDescriptors)
    {
    	final List/*<ContentDescriptor>*/ result = new ArrayList();
    	for (int i = 0; i < contentDescriptors.length; ++i)
    	{	if (isCompatible(contentDescriptors[i]))
    			result.add(contentDescriptors[i]);
    	}
    	
		final ContentDescriptor[] arrayResult = new ContentDescriptor[result.size()];
		for (int i = 0; i < result.size(); ++i)
			arrayResult[i] = (ContentDescriptor) result.get(i);
		return arrayResult;
    }
    
    private TrackConfig[] trackConfigs;
    
    public boolean aboutToDisplayPanel(Object prevId) {
        
        if (prevId == getBackPanelDescriptor())
        {
        	// forward transition 
	        ContentDescriptor[] contentDescriptors = result.processor.getSupportedContentDescriptors();
	        
	        if (contentDescriptors.length == 0)
	        {	showError("Processor supports no content descriptors");
	        	return false;
	        }
	        
	        contentDescriptors = compatible(contentDescriptors);	// eliminate non-RTP-compatible ones.
	        
	        if (contentDescriptors.length == 0)
	        {	showError("Processor supports no compatible content descriptors");
	        	return false;
	        }
	        
	        getContentAndTrackFormatPanel().getComboFormat().setModel(new javax.swing.DefaultComboBoxModel(contentDescriptors));
	           
	        int contentDescriptorIndexToSet = 0;
	        
	        if (config.contentDescriptor != null)
	        {
	        	for (int i = 0; i < contentDescriptors.length; ++i)
	        	{	if (config.contentDescriptor.equals(contentDescriptors[i]))
	        		{	contentDescriptorIndexToSet = i;
	        			break;
	        		}
	        	}
	        }

	        config.contentDescriptor = contentDescriptors[contentDescriptorIndexToSet]; // save, in case different

	        
	        getContentAndTrackFormatPanel().getComboFormat().setSelectedItem(config.contentDescriptor);

	        try 
	        {
				result.step2_setContentDescriptor(config);
			} catch (WizardStepException e) 
			{
				showError(e);
				return false;
			}
			
			// TODO: 
			
	        
	        // TODO: if the users changes the combo, we need to change the tracks.
	        
	        final TrackControl trackControls[] = result.processor.getTrackControls();
	        if (trackControls == null || trackControls.length < 1)
	        {	showError("No tracks available");
	        	return false;
	        }
	        
	        trackConfigs = new TrackConfig[trackControls.length];
	        for (int i = 0; i < trackConfigs.length; ++i)
	        	trackConfigs[i] = new TrackConfig();
	        
	        for (int i = 0; i < trackControls.length; i++)
			{
				Format[] formats = trackControls[i].getSupportedFormats();	// TODO: FMJ returns just a few generic formats, and JMF returns a lot of specific formats (for raw), and all rtp audio formats (for raw rtp)
				
				/*
				 	Available track format: dvi/rtp, 8000.0 Hz, 4-bit, Mono
					Available track format: dvi/rtp, 11025.0 Hz, 4-bit, Mono
					Available track format: dvi/rtp, 22050.0 Hz, 4-bit, Mono
					Available track format: ULAW/rtp, 8000.0 Hz, 8-bit, Mono, FrameSize=8 bits
					Available track format: gsm/rtp, 8000.0 Hz, Mono, FrameSize=264 bits
				 */
				
				if (formats == null)
				{
					logger.warning("No supported formats (formats=null) for track " + i);
					trackConfigs[i].enabled = false;
					trackConfigs[i].format = null;
					continue;
				}
				if (formats.length == 0)
				{
					logger.warning("No supported formats (formats.length=0) for track " + i);
					trackConfigs[i].enabled = false;
					trackConfigs[i].format = null;
					continue;
				}
				
				for (int j = 0; j < formats.length; ++j)
				{
					logger.info("Available track format: " + formats[j]);
				}
				
				// TODO: hard-coded
				getContentAndTrackFormatPanel().getAudioFormatPanel().getComboAudioEncoding().setModel(
						new javax.swing.DefaultComboBoxModel(new String[] { AudioFormat.ULAW_RTP }));
//				getContentAndTrackFormatPanel().getAudioFormatPanel().getComboAudioEncoding().setModel(
//						new javax.swing.DefaultComboBoxModel(new String[] { AudioFormat.LINEAR }));
				getContentAndTrackFormatPanel().getAudioFormatPanel().getComboAudioSampleRate().setModel(
						new javax.swing.DefaultComboBoxModel(new String[] { "8000" }));
				
				if (config.trackConfigs != null && config.trackConfigs.length >= i+1 && config.trackConfigs[i].format instanceof AudioFormat)
				{	// copy from prefs
					trackConfigs[i].format = config.trackConfigs[i].format;
					trackConfigs[i].enabled = config.trackConfigs[i].enabled;
				}
				else
				{	// default
					trackConfigs[i].format = new AudioFormat(AudioFormat.ULAW_RTP, 8000.0, 8, 1, AudioFormat.LITTLE_ENDIAN, AudioFormat.SIGNED); // TODO: hard-coded.
					trackConfigs[i].enabled = trackControls[i].isEnabled();
				}
				
				boolean formatOk = false;
				for (int j = 0; j < formats.length; ++j)
				{
					logger.fine("Track " + i + " supports format " + formats[j]);
					if (formats[j].matches(trackConfigs[i].format))
					{
						// TODO: we only support 1 audio track.  Enforce it.
						getContentAndTrackFormatPanel().addTrack(i, trackConfigs[i].enabled, (AudioFormat) trackConfigs[i].format);
						formatOk = true;
						break;
					}
				}
				
				if (!formatOk)
				{
					trackConfigs[i].enabled = false;
					trackConfigs[i].format = null;
				}
	
						
				
			}
        }
        
        return true;
    }    
    
	public boolean aboutToHidePanel(Object idOfNext)
	{
		if (idOfNext == getNextPanelDescriptor())
		{
			// forward transition
	        
	        for (int i = 0; i < trackConfigs.length; i++)
	        {
	        	trackConfigs[i].enabled = getContentAndTrackFormatPanel().getTrackControlPanel(i).getCheckBoxEnableTrack().isSelected();
	        	
	        	if (trackConfigs[i].enabled)
	        	{	// TODO: do the conversion to Format here, so we can validate.
	        		trackConfigs[i].format = getContentAndTrackFormatPanel().getTrackControlPanel(i).getAudioFormatPanel().getAudioFormat();
	        	}
	        }
	        
	        try
			{
	        	config.trackConfigs = trackConfigs;
				result.step3_setTrackConfigs(config);
			} catch (WizardStepException e)
			{
				showError(e);
				return false;
			}

	        return true;
		}
		
		return super.aboutToHidePanel(idOfNext);
	}

    



}
